package com.apestech.framework.xml.plugin;

import com.apestech.formwork.xml.core.NodeVar;
import com.apestech.framework.file.IdFile;
import com.apestech.framework.json.JSONObject;
import com.apestech.framework.util.FileUtil;
import com.apestech.framework.util.LocalVariable;
import com.apestech.framework.util.StringUtil;
import com.apestech.framework.xml.ReadXmlNodeInter;
import com.apestech.framework.xml.modul.XmlFile;
import com.apestech.framework.xml.XmlSysConfig;
import com.apestech.framework.xml.modul.Xml_File;
import com.apestech.framework.xml.pub.ReadXml;
import org.dom4j.Element;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import static com.apestech.framework.xml.plugin.XmlIdVar.STR_TYPE.DIR_PATH;

/**
 * @author hup
 * @create 2019-10-11-10:53
 */
public class XmlId extends StringUtil{
    private String id;
    private String dir;
    private String pathKey;
    private String theme;
    private int pathSize;
    private ArrayList<String> pathlist=new ArrayList<String>();
    XmlSysConfig config=LocalVariable.getConfig();
    private XmlFile xmlfile=new XmlFile();
    private JSONObject filelist;
    private XmlIdVar.STR_TYPE str_type;
    private String xml_str;
    private boolean isWorkDir;

    public XmlId() throws Exception {  //dir批量操作
    }

    public XmlId(String id) throws Exception {
        initVar(id);
    }

    public XmlId(String id, String nodeName) throws Exception {
        initVar(id);
        xmlfile.setNodename(nodeName);
    }

    public XmlId(String str, XmlIdVar.STR_TYPE str_type) throws Exception {
        xml_str=str;
        this.str_type=str_type;
    }

    public void setStrInput(String str, XmlIdVar.STR_TYPE str_type)  throws Exception {
        xml_str=str;
        this.str_type=str_type;
    }

    private void getSqlNode() throws Exception {
        if(str_type==null) return;
        ReadXml xml=new ReadXml();
        switch (str_type){
            case FILE_PATH:{
                if(!FileUtil.isFileExist(xml_str)) throw new Exception("请填入有效的文件名！");
                xml.loadXmlFromFile(xml_str);
                xmlfile.setFile(xml_str);
                break;
            }
            case XML_STR:{
                xml.loadXmlFromString(FileUtil.getXmlStr(xml_str), false);
                break;
            }
            case XML_SQL:{
                xml.loadXmlFromString(FileUtil.getXmlStr(xml_str), true);
                break;
            }
        }
        xmlfile.setRoot(xml.getRoot());
        if(xmlfile.getId()==null && "select".equals(xmlfile.getNodename())){
            xmlfile.setNode(xml.getRoot());
        }
    }

    private void initVar(String id) throws Exception {
        this.id=id;
        xmlfile.setAllid(id);
        setDir();
        init(id);
    }

    public void setPath(String dir) {
        this.dir = dir;
    }

    private void setDir(){
        if(dir==null) dir=LocalVariable.getRootDir();
        int len=dir.length();
        String s=dir.substring(len-1, len);
        if(!s.equals(File.separator)) dir=dir+File.separator;
        pathKey= NodeVar.getNodeMap().getString(xmlfile.getNodename());
        xmlfile.setPrefix(pathKey.toUpperCase()+"_");
        JSONObject p=NodeVar.getPathMap();
        ArrayList<String> klist=p.getKeylist();
        pathlist.add(pathKey);
        if(theme!=null) pathlist.add(pathKey+theme+File.separator);
        pathSize=klist.size();
        for(int i=0; i<pathSize; i++){
            String k=klist.get(i);
            if(!k.equals(pathKey)){
                pathlist.add(k);
                if(theme!=null) pathlist.add(k+theme+File.separator);
            }
        }
    }

    private void init(String queryId) throws Exception {
        if(xmlfile.getRoot()!=null) return;
        for(int i=0; i<pathSize; i++){
            String p=dir+pathlist.get(i)+ File.separator;
            if(!FileUtil.fileExists(p)) p=dir+pathlist.get(i).toUpperCase()+ File.separator;
            initDir(queryId, p);
            if(xmlfile.getFile()!=null){
                break;
            }
        }
        if(xmlfile.getFile()==null) {
            throw new Exception("该查询文件不存在，请检查传入的查询ID中文件部分的数据！");
        }
    }

    private void initDir(String queryId, String dir) throws Exception {
        xmlfile=config.getXmlFile(xmlfile.getAllid());
        if(xmlfile==null){
            xmlfile=new XmlFile();
            xmlfile.setAllid(queryId);
        }
        IdFile idFile=new IdFile(dir, queryId, "xml");
        idFile.getData();
        this.id=idFile.getId();
        xmlfile.setId(idFile.getId());
        xmlfile.setFile(idFile.getResultFile());
    }

    public Element getNode() throws Exception {
        if(str_type!=null){
            getSqlNode();
            //if(xmlfile.getNode()==null)
                setNode(xmlfile, null, null, xmlfile.getNodename());
        } else {
            if(xmlfile.getNode()==null){
                ReadXml xml=new ReadXml();
                xml.loadXmlFromString(getXmlStr(xmlfile, xmlfile.getFile()), true);
                xmlfile.setRoot(xml.getRoot());
                setNode(xmlfile, id, xmlfile.getNodename(), null);
                config.setXmlFile(xmlfile);
            }
        }
        return xmlfile.getNode();
    }

    private void setNode(XmlFile xmlf, String id, String nodeName, String xpath) throws Exception {
        if(xpath!=null){
            if(xmlf.getRoot().selectSingleNode(xpath)==null) throw new Exception("传入结点ID ["+xpath+"]有误!");
            xmlf.setNode((Element) xmlf.getRoot().selectSingleNode(xpath));
        }
        if(id!=null){
            Element node=(Element) xmlf.getRoot().selectSingleNode(nodeName+"[@id='"+id+"']");
            if(node==null) node=(Element) xmlf.getRoot().selectSingleNode(id);
            xmlf.setNode(node);
        }
    }

    private Element getRootFromFile(XmlFile xmlf, String file, boolean hasHead) throws Exception {
        ReadXml xml=new ReadXml();
        xml.loadXmlFromString(getXmlStr(xmlf, file), hasHead);
        return xml.getRoot();
    }

    public void getXmlFile(Object param, ReadXmlNodeInter readXmlNodeInter, String nodeName) throws Exception {
        if(!FileUtil.isFileExist(xml_str)) throw new Exception("请填入有效的目录名！");
        filelist=new JSONObject();
        dir=xml_str;
        isWorkDir=dir.indexOf(LocalVariable.getRootDir())>=0;

        ArrayList<String> list=FileUtil.getFieldList(dir);
        int len=list.size();
        for(int i=0; i<len; i++){
            String sfile=list.get(i);
            XmlFile xmlf=new XmlFile();
            xmlf.setPrefix(getPrefixFromDir(sfile));
            xmlf.setFile(sfile);
            boolean isCache=false;
            if(isWorkDir){
                Xml_File xml_file=config.getXml_File(sfile);
                if(xml_file!=null){
                    xmlf.setXml_File(xml_file);
                } else {
                    isCache=true;
                    xmlf.setRoot(getRootFromFile(xmlf, sfile, true));
                }
            } else {
                if(filelist.get(sfile)!=null){
                    xmlf.setRoot((Element) filelist.get(sfile));
                } else {
                    xmlf.setRoot(getRootFromFile(xmlf, sfile, true));
                    filelist.put(sfile, xmlf.getRoot());
                }
            }
            if(param instanceof String){
                String sid=(String)param;
                if(nodeName==null) ReadNode(xmlf, sid, readXmlNodeInter, isCache);
                else {
                    xmlf.setNodename(nodeName);
                    setNode(xmlf, sid, nodeName, null);
                    readXmlNodeInter.ReadNode(xmlf.getRoot(), xmlf.getNode(), sid);
                }
            } else if(param instanceof ArrayList){
                ArrayList<String> nlist= (ArrayList<String>) param;
                int nlen=nlist.size();
                for(int n=0; n<nlen; n++){
                    ReadNode(xmlf, nlist.get(n), readXmlNodeInter, isCache);
                }
            }
        }
    }

    private void ReadNode(XmlFile xmlf, String snode, ReadXmlNodeInter readXmlNodeInter, boolean isCache) throws Exception {
        List<Element> nodes=xmlf.getRoot().elements(snode);
        int len=nodes.size();
        for(int i=0; i<len; i++){
            Element node=nodes.get(i);
            String sid=node.attributeValue("id");
            xmlf.setAllid(xmlf.getPrefix()+"."+sid);
            xmlf.setNodename(snode);
            readXmlNodeInter.ReadNode(xmlf.getRoot(), node, snode);
            if(isCache) config.setXmlFile(xmlf);
        }
    }

    private String getPrefixFromDir(String file){
        int max=2;
        file=file.substring(file.indexOf(":")+1+ File.separator.length(), file.length());
        file=file.replace(File.separator, "#");
        String[] list=file.split("#");
        int len=list.length;
        if(len<max+1) return file.replace("#", ".");
        else {
            String s="";
            for(int i=len-max; i<len; i++){
                if(!s.equals("")) s=s+".";
                s=s+list[i];
            }
            return s;
        }
    }

    private String getXmlStr(XmlFile xmlf, String file) throws Exception {
        if(xmlf.getXml()==null){
            xmlf.setXml(FileUtil.getXmlStr(file));
        }
        return xmlf.getXml();
    }

    public String getNodename() {
        return xmlfile.getNodename();
    }

    public void setNodename(String nodename) {
        xmlfile.setNodename(nodename);
    }

    public String getTheme() {
        return theme;
    }

    public void setTheme(String theme) {
        this.theme = theme;
    }

    public String getId() {
        return id;
    }

    public XmlFile getXmlfile() {
        return xmlfile;
    }

    public void setXmlfile(XmlFile xmlfile) {
        this.xmlfile = xmlfile;
    }

    public void setId(String id) {
        this.id = id;
    }
}
